home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / database / db3stock / db3stock.doc < prev    next >
Text File  |  1986-04-13  |  20KB  |  355 lines

  1. As programmers, we all have several creative problem-solving routines we have
  2. written for clients that we like to brag about -- they were clever, compact,
  3. and tight.  They might have even compiled and run perfectly the first time.
  4. But let's face it -- writing meaningful, consistent user interfaces with
  5. exceptional attention to thorough error-trapping takes a lot of TIME, perhaps
  6. even the most time we spend in the actual coding development and code writing
  7. process.  It certainly increases the bulkiness of our code (by way of many
  8. K-bytes of TEXT data structures).
  9.  
  10. But this aspect of programming -- user interface --is the singularly most
  11. important determining factor of client satisfaction.  As a maintenance
  12. programmer, I have been apalled at the abject lack of user interfaces.  In
  13. one situation, the previous coder before me wrote coder before me wrote no
  14. code to give the user any status messages indicating what was happening
  15. when the user was finished working with data. i.e., "Saving the new data to
  16. disk", "Deleting your record from the file", etc.).  The little red light
  17. on the drive may have come on, but what was happening was anyone's guess.
  18. When an internal error from an error trap was encountered, there were often
  19. no messages -- simply a return to the previous calling menu before the error.
  20. Apparently, the user was supposed know what error had been committed.  Even
  21. worse, some of the important data input was not error-trapped that could
  22. overwrite data in an unintended record, or simply crash the program.
  23.  
  24. In virtually EVERY maintenance program I have ever worked on, I have been
  25. absolutely shocked at the AUSTERITY of the input screens I have seen.  There
  26. is no regard for the fact that clients have to look at that screen, perhaps
  27. as often as long as eight full hours EVERY WORKING DAY.  If the screen is
  28. dull and unattractive, how long do you think it will be before they start
  29. making mistakes--and then blaming YOU, the programmer, for data crashes???
  30.  
  31. The recently vast improving user interfaces in commercially available general-
  32. user software (word processors, database managers, spreadsheets) makes
  33. inexcusable this "let's-continue-the-awe-about-computers-and-programming-
  34. with-mystery" fashion of doing business with a client.  I predict in a few
  35. years anyone thinking that nothing less than absolutely superior user
  36. interfaces --including top-notch, attractive screens-- for a common end user
  37. will render that individual unemployable in programming. And since dbaseIII
  38. handles much of our file handling activities with single lines of code and/or
  39. commands, there is now more time for programmers to spend more of their
  40. precious time with good user interface development.
  41.  
  42. To that end, then, I have developed some simple, yet extremely useful
  43. subroutines that can be used almost as meta-commands.  It makes development
  44. a lot simpler.
  45.  
  46.  
  47.  
  48.  
  49. This DB3STOCK.ARC file contains the following files:
  50.  
  51.  
  52. DB3STOCK.DOC -- this (introductory) file
  53.  
  54.  
  55.  
  56. bigboxdt.prg -- A simple "MAIN MENU" type, graphics-drawn box that centers,
  57.                 highlights, and displays a header message at the top inside
  58.                 line of the box, and then displays the date and time at the
  59.                 left and right sides of the box, respectively.
  60.  
  61. boxclear.prg -- A routine that clears the inside of BIGBOXDT without having
  62.                 to clear the screen and redraw it.  This is helpful for
  63.                 continuous LISTs or DISPLAYs of data.  The starting line of
  64.                 the clearing procedure is defined by the numeric variable
  65.                 LN, and it is helpful to have it user defineable BEFORE ent-
  66.                 ering the routine, as you may have subheaders towards the
  67.                 top of the screen that you do NOT want to erase and redraw.
  68.  
  69. smallbox.prg -- A routine that creates a smaller box on the screen.  Useful
  70.                 for help screens or flagging important data entry.
  71.  
  72. slinboxm.prg -- A routine that draws a single line box in the middle of the
  73.                 screen, and then centers, highlights and displays a user-
  74.                 defined message (MSG) inside the box.
  75.  
  76. slinboxt.prg -- A routine that draws a single line box at the top of the
  77.                 screen, and then centers, highlights and displays a user-
  78.                 defined message (MSG) inside the box.
  79.  
  80. slinboxb.prg -- A routine that draws a single line box at the bottom of the
  81.                 screen, and then centers, highlights and displays a user-
  82.                 defined message (MSG) inside the box.
  83.  
  84. dlinboxm.prg -- These three programs are indentical to their "SLINBOXx" sub-
  85. dlinboxt.prg -- routines above, with the exception that they use a double
  86. dlinboxb.prg -- line graphic-oriented box instead of the single line box.
  87.  
  88. linprm23.prg -- This is a metacommand that will save no ends of programming,
  89.                 particularly where multiple branches are about to occur. Let's
  90.                 take an example: you have displayed a screen of data from a
  91.                 file record.  The decision list is as follows:
  92.  
  93.                     "<A>dd  <E>dit  <D>elete  <N>ext  <P>revious  <X>Exit"
  94.  
  95.                 Merely define the variable "MSG" as the text in quotes above.
  96.                 Define the variable "TEST" as the string literal :"AEDNPX" .
  97.                 Define TZ as " ".  Now the next line of code would be "DO
  98.                 LINPRM23".  The routine centers, highlights and displays the
  99.                 text and waits for the <A>, <E>, <D>, <N>, <P>, or <X> key
  100.                 to be pressed.  The input is automatically made uppercase.
  101.                 And only those individual keys from "TEST" are acceptable
  102.                 input. The final code in this example would look like this:
  103.  
  104.                 tz=" "
  105.                 test="AEDNPX"
  106.                 msg="<A>dd  <E>dit  <D>elete  <N>ext   <P>revious  <X>Exit"
  107.                 do linprm23
  108.  
  109.                 You are now free to use the appropriate IF/ENDIF or
  110.                 DO CASE/CASE statements -- based on the key pressed.
  111.  
  112. linmsg23.prg -- Sometimes you will want to put a message on the screen and
  113.                 wait for the user to acknowledge the message.  That is exactly
  114.                 what this routine does.  You define the message, and it
  115.                 centers, highlights, and displays the message, and then waits
  116.                 for any keystroke.  As in the subroutine above, you define the
  117.                 "MSG" and "TZ" variables before entering the routine.  This
  118.                 routine is FAR more attractive than the WAIT statement, and
  119.                 is more helpful to an end user because you can customize the
  120.                 message to help guide the user when he continues.
  121.  
  122. prtmsg23.prg -- This routine is identical to the routine above, except that
  123.                 no input of any kind by the user is required.  It merely high-
  124.                 lights, centers, and displays the message ("MSG") at the bottom
  125.                 of the screen.  This routine is immensely useful for writing
  126.                 those oh-so-needed messages like, "Saving new data to disk"
  127.                 or "ACCOUNTS CLOSING IN PROGRESS.  Please wait."  You can
  128.                 INCLUDE MACRO variables as part of the message for further
  129.                 convenience, such as :
  130.  
  131.                 msg="Department "+&deptID+" has "+str(records,4,0)+" entries."
  132.                 DO PRTMSG23
  133.  
  134. getfld23.prg -- This is one of my favorite routines.  If I want a user to input
  135.                 data that is not part of the input screen nor part of the data
  136.                 file (say, it is part of an overall calculation or series of
  137.                 calculations), and I DON'T WANT TO LOSE ANY OF THE SCREEN DATA
  138.                 DISPLAYED, I can avoid drafting the code that redraws the
  139.                 screen and data by getting the information at the bottom of
  140.                 the screen.  It is attractive, gets the immediate and proper
  141.                 attention of the user, and allows the coder to focus on getting
  142.                 data!  An example:
  143.  
  144.                 Mcost=0.00     : * the target data variable for user input.
  145.                 FEELD=space(6) : * the length of the variable, pict "9999.99"
  146.                 kol=0
  147.                 msg="ENTER the total cost of the Advertisement :"
  148.                 do getfld23
  149.                 do while Mcost<=0 .or. Mcost>7290.05
  150.                    Mcost=0
  151.                    @ 23,kol get Mcost picture "9999.99"  : * length=6 spaces
  152.                 enddo
  153.  
  154. prevmo.prg   -- A routine that calculates what the actual previous calendar
  155.                 month is, REGARDLESS of what the current system date is.
  156.  
  157. nextmo.prg   -- A routine that calculates what the actual NEXT calendar month
  158.                 is, regardless of what the current system date is.
  159.  
  160. passwerd.prg -- A fully functional password program.  It is misspelled on pur-
  161.                 pose.  Many public domain and commercially available dbase rou-
  162.                 tines use "PASSWORD.PRG" as its namesake.  I don't want to
  163.                 accidentally overwrite any files you may have by that name when
  164.                 you copy this file!  You must first create a file from
  165.                 within dbase III, called "SECURITY.DBF".  It consists of one
  166.                 field, of character, and 12 characters in length.  The field
  167.                 name should be called "ENTEROK".  Then create a temporary
  168.                 ".PRG" file which contains ONLY the block of code from within
  169.                 "PASSWERD.PRG" that starts from the comment: "PASSWORD ADDITION
  170.                 ROUTINE starts here" to the comment: "PASSWORD ADDITION ROUTINE
  171.                 ends here".  Run that as a separate program and the first
  172.                 record in the file will be the MASTER PASSWORD.  ONLY the
  173.                 MASTER PASSWORD will allow other passwords to be logged into
  174.                 the SECURITY file.  Just for fun, do a DISPLAY ALL of the
  175.                 SECURITY.dbf file records from the dbase III interpreter.
  176.  
  177. lincount.prg -- is a routine that will keep a running count of all information
  178.                 written to the screen or to the printer, and how many lines you
  179.                 have left before the screen must be refreshed (BOXCLEAR), or
  180.                 a page EJECT invoked.  It also allows 6 headers to be used as
  181.                 part of the top of your page, whether you are using to screen
  182.                 or printer.
  183.  
  184. displrut.prg -- is a text file only. SEE DB3STOCK.TXT below.
  185.  
  186.  
  187. You will notice that some of these routines require that several variables
  188. need to be initialized BEFORE entering the routine.  First, you might ask, "Why
  189. not use the dbaseIII convention,  DO <subroutine> WITH <parameters>?" Secondly,
  190. you might ask, "What if my application is currently using the same named
  191. variables as the routines above?"
  192.  
  193. In answer to the first question,
  194. I avoid DO WITH constructs because you have to use a TWO SETS of variables to
  195. successfully complete a DO WITH procedure -- one set to pass variables TO
  196. the routine, and one set to RECEIVE the passed variables.  You could use the
  197. same variables as parameters, but dbase III has a myriad of memory variable
  198. handling functions (RESTORE from <filename>.MEM [ADDITIVE], CLEAR [ALL | LIKE
  199. <skeleton>, PUBLIC,PRIVATE,HIDDEN) that can, in conjunction with each other,
  200. often create memory management conflicts, even amongst the most organized of
  201. us.  The dbase III Advanced Programmer's Guide (Castro, et. al.) strongly
  202. advises against identical variable/parameter passing.  Translation:  it's
  203. probably going to have bugs if you do.  I always initialize variable(s) before
  204. entering routines because :  (1) it is ALWAYS easier to write  (2) you have
  205. fewer variable names in the long run to trace/debug for any given routine(s),
  206. and  (3) - whether the variables are PUBLIC or PRIVATE, initializing them
  207. BEFORE invoking the routine makes them accessible to that called routine.
  208. Frankly, I've hated PUBLIC/PRIVATE nonsense.  Initializing variables just
  209. before use is almost a sure way of emulating a "globalness" of your variable
  210. condition -- something I always enjoyed about dbase II and BASIC.
  211.  
  212. In answer to the second question, I find that most applications programmers
  213. have a unique style to their memory variable name assignments.  In all the
  214. maintenance program work I have done, I have not yet found ANY of my variable
  215. names in my routines to be in conflict with the assignments of the code I had
  216. to maintain.  It might just be luck, but I rather doubt it.  If you do have
  217. problems with variable names, you will have to rename yours or rename mine.
  218. As a matter of PRAGMATISM, (not ego), you might find it more time saving to
  219. rename YOURS, for two reasons:  (1)  You know where all the locations of
  220. your variables are, what they do, what they stand for, and what effect they
  221. have on every aspect of all the other modules in your application.  It's your
  222. own code, so who else but you would know what affect variable naming
  223. procedures and initialization assignments would do to those modules?
  224. (2)  Many of the subroutines above CALL EACH OTHER, "PASSWERD.PRG" in
  225. particular.  You know the domino theory.  And it certainly applies to
  226. variables in programming -- one module SNAFU's, and they probably all will
  227. have a large or small SNAFU in them somewhere.
  228.  
  229. A final word about these routines.  They take great care in forecasting the
  230. environment that needs to exist after they have been executed.  For example,
  231. the routines that contain "??????23.PRG" initialize the set color commands,
  232. clear from line 23 any existing "MSG", and print the new one.  Where key
  233. input is required, line 23 is CLEARED, so you don't have to remember to code
  234. that yourself.  Where it is not required, of course, the "MSG" remains on
  235. screen, as the routine assumes the condition exhibited by the message remains
  236. in effect until another message (or screen!) indicates otherwise.
  237.  
  238.  
  239.  
  240. DB3STOCK.OBJ -- an 8088-relocatable object code file, which can be linked
  241.                 with PLINK86, in the formation of final dbaseIII compiled
  242.                 ".EXE" programs.  It is a Clipper (TM) compiled file of all
  243.                 the source programs (subroutines) above.  If you write in
  244.                 dbaseIII and compile your applications using the Clipper
  245.                 compiler, you do not need to recompile these programs.  Merely
  246.                 include this file as the LAST object code file to link with
  247.                 your other object code files, and they will be available to
  248.                 your applications program.  The only stipulation is, of
  249.                 course, that when compiling your other programs that make up
  250.                 the total of your application is that you do NOT use the
  251.                 convention,
  252.  
  253.                                     "clipper <filename>"
  254.  
  255.                 where <filename> is the main calling program that calls all
  256.                 other programs.  Rather, use the convention:
  257.  
  258.                                     "clipper @<filelist>.CLP"
  259.  
  260.                 where <filelist>.CLP is an ascii text file listing of ALL the
  261.                 programs you need compiled for your application.  Don't forget,
  262.                 in using this latter convention, the first filename in the
  263.                 <filelist> should be <filename>, i.e., the main calling
  264.                 program that calls all other programs.  DO NOT list any of
  265.                 the subroutines above in your <filelist>, as the DB3STOCK.OBJ
  266.                 file already contains them.
  267.  
  268. DB3STOCK.TXT -- An ascii text file, which contains the following subroutines:
  269.  
  270.                 bigboxdt.prg
  271.                 boxclear.prg
  272.                 smallbox.prg
  273.                 lineboxm.prg
  274.                 slinboxm.prg
  275.                 slinboxt.prg
  276.                 slinboxb.prg
  277.                 dlinboxm.prg
  278.                 dlinboxt.prg
  279.                 dlinboxb.prg
  280.                 linprm23.prg
  281.                 linmsg23.prg
  282.                 prtmsg23.prg
  283.                 getfld23.prg
  284.                 prevmo.prg
  285.                 nextmo.prg
  286.                 passwerd.prg
  287.                 lincount.prg
  288.                 *  displrut.prg
  289.  
  290.                 DISPLRUT.PRG is an educational text file, not a dbaseIII
  291.                 executable PRG file per se.  It is invaluable as a routine
  292.                 to write to EITHER print or to screen, and is easily custom-
  293.                 izable.
  294.                 Again, these files are identical to the prg's described above
  295.                 but they are collected into one file for archival purposes.
  296.  
  297.  
  298. DB3STOCK.SKL -- An ascii text file, which contains the following procedures:
  299.  
  300.                 procedure bigboxdt
  301.                 procedure boxclear
  302.                 procedure smallbox
  303.                 procedure lineboxm
  304.                 procedure slinboxm
  305.                 procedure slinboxt
  306.                 procedure slinboxb
  307.                 procedure dlinboxm
  308.                 procedure dlinboxt
  309.                 procedure dlinboxb
  310.                 procedure linprm23
  311.                 procedure linmsg23
  312.                 procedure prtmsg23
  313.                 procedure getfld23
  314.                 procedure prevmo
  315.                 procedure nextmo
  316.                 procedure passwerd
  317.  
  318.                 These files are IDENTICAL to the PRG's as listed above, but
  319.                 they have been put into a procedure file.  You can then do
  320.                 one of two things with this file:
  321.                 1).  Merge it directly at the end of any of your current
  322.                      dbaseIII procedure file and you can now make any calls
  323.                      to the above subroutines directly.
  324.                 2).  Do you use the new GENIFER (TM) program from Bytel Corporation?
  325.                      (It is an OUTSTANDING APPLICATIONS GENERATOR -- the best I
  326.                      have EVER seen.  It is worth every penny of the $295.00 I
  327.                      paid for it.  I spent about six hours giving GENIFER the
  328.                      parameters for the code I needed generated.  GENIFER took
  329.                      about 30 minutes generating the code.  I then charged the
  330.                      client 800 bucks.  The client loved it, and so did I.)
  331.                      Using a simple text editor, I have merged DB3STOCK.SKL to
  332.                      the very end of the three GENIFER ".SKL" files that come
  333.                      with GENIFER.  The last line of every GENIFER ".SKL" file
  334.                      contains the line,
  335.                                         "wd* EOF {{program}}"
  336.                      where GENIFER replaces "{{program}}" with your program
  337.                      name when the program is generated.  JUST ABOVE THIS LINE
  338.                      use the MERGE function (or block insert or block merge
  339.                      or file merge or whatever your word processor/editor
  340.                      calls it) of "DB3STOCK.SKL" INTO each of these GENIFER
  341.                      ".SKL" files.  Every program now generated with GENIFER
  342.                      will now also generate these subroutines for your program
  343.                      AUTOMATICALLY.
  344.  
  345.  
  346. Hope these routines are of some benefit.  Give me some feedback on how you
  347. might find ways to improve on them!
  348.  
  349.  
  350.  
  351. Scott Brock
  352. The Outer Bridge
  353. 1600 San Fernando Blvd.  Suite 235
  354. Burbank, CA.  91504
  355. 1-818-848-8955